package device;

import java.util.ArrayList;

public class SubNet {
	public SubNet(String subNetAddr, String subNetMask) {
		subNetID = ++subNetNum;
		this.subNetAddr = subNetAddr;
		this.intSubNetMask = parseDotted(subNetAddr);
		this.subNetMask = subNetMask;
		this.intSubNetAddr = parseDotted(subNetAddr);
	}

	public int getSubNetID() {
		return subNetID;
	}
	
	/**
	 * test if a host belongs to this sub net
	 * 
	 * @param h
	 *            the host
	 * @return true if in, false otherwise
	 */
	public boolean in(Host h) {
		int[] arrayedAddr = parseDotted(h.dottedNetAddress);
		// if error occurs
		if (arrayedAddr == null)
			return false;
		// see whether h in this sub net according to IP address and sub net mask
		for (int i = 0; i < arrayedAddr.length; i++)
			arrayedAddr[i] &= intSubNetMask[i];
		return compareByte(arrayedAddr, intSubNetAddr);
	}

	/**
	 * parse address from dot-form to byte-form
	 * 
	 * @param dottedAddr
	 *            address in dot-form
	 * @return address in byte-form, null if error occurs
	 */
	private int[] parseDotted(String dottedAddr) {
		if (dottedAddr == null)
			return null;
		
		String[] arrayedStrAddr = dottedAddr.split(".");
		
		if (arrayedStrAddr.length != IPv4)
			return null;
		
		// parse address to integer
		int[] res = new int[IPv4];
		for (int i = 0; i < IPv4; i++)
			res[i] = Integer.parseInt(arrayedStrAddr[i]);
		return res;
	}
	
	/**
	 * compare two byte-form integer
	 * 
	 * @param a
	 *            first operand
	 * @param b
	 *            second operand
	 * @return true if they are same, false if not
	 */
	private boolean compareByte(int[] a, int[] b) {
		if (a.length != b.length)
			return false;
		for (int i = 0, bound = a.length; i < bound; i++)
			if (a[i] != b[i])
				return false;
		return true;
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof SubNet) {
			SubNet s = (SubNet) o;
			if (s.getSubNetID() == subNetID
					|| (s.subNetAddr == subNetAddr && s.subNetMask == subNetMask))
				return true;
		}
		return false;
	}

	public String subNetMask;
	public int[] intSubNetMask;
	public String subNetAddr;
	public int[] intSubNetAddr; // 32-bit integer, in byte-form
	public ArrayList<Host> hosts = new ArrayList<Host> ();
	private int subNetID;
	private static int subNetNum = 0;
	private static final int IPv4 = 4;
}
